

ab = list("abcdefghijklmnopqrstuvwxyzABCDEFGHIJLKMNOPQRSTUVWXYZ")
ab_ = ab + ["_"]
num = list("0123456789")
abnum_ = ab_ + num
newline = list("\r\n")
sign = list(".,<>?/;|+=-*&^%$@S!~`") + [":"]        # 现在把冒号也视为算符
multi = ["+=", "-=", "*=", "/=", "**", "%=", "//=", "==", "!=", ">=", "<=", "&=", "$.", "$|", "@@", "@@@", "~~"]

def find_multi(s):
    l = []
    for m in multi:
        if m[:-1].startswith(s):
            l.append(m[len(s):len(s)+1])
    return l
import time
class Stream:
    def __init__(self, s, p=0):
        self.__s = s
        self.__p = p

    def pop(self):
        #time.sleep(0.01)
        #print('pop', repr(self.peek(5)))
        return self.__s[self.__p], Stream(self.__s, self.__p + 1)

    def push(self):
        #time.sleep(0.01)
        #print('push', repr(self.peek(5)))
        return Stream(self.__s, self.__p - 1)
        
    def peek(self, n=1):
        return self.__s[self.__p: self.__p+n]

def read_doc(se):
    acc = [('', [])]
    
    while True:
        ch, se = se.pop()
        if ch == '\0':
            if len(acc[-1][1]) > 0 and \
               isinstance(acc[-1][1][-1], Line) and \
               acc[-1][1][-1].comma == True:
               raise Exception('wrong comma 1')
            while True:
                s1, a1 = acc.pop()
                if s1 == '':
                    return Doc(a1), se
                else:
                    if len(acc[-1][1]) > 0 and \
                       isinstance(acc[-1][1][-1], Line) and \
                       acc[-1][1][-1].comma != True:
                       raise Exception(f'wrong comma 2 {a1}')
                    
                    acc[-1][1].append(Block(s1, a1))
        elif ch in '\r\n':
            pass
        else:
            r, se = read_line(se.push())
            ns, na = acc[-1]
            if r is None:
                continue
            elif r.space == '' and ns == '':
                #判冒号
                if len(na) > 0 and \
                   isinstance(na[-1], Line) and \
                   na[-1].comma == True:
                   raise Exception('wrong comma 3')
                    
                na.append(r)
            elif r.space > '' and ns == '':
                acc.append((r.space, [r]))
            elif r.space == ns:
                #判冒号
                if len(na) > 0 and \
                   isinstance(na[-1], Line) and \
                   na[-1].comma == True:
                   raise Exception('wrong comma 4')
                   
                na.append(r)
            elif r.space > ns:
                acc.append((r.space, [r]))
            elif r.space < ns:
                while True:
                    ns, na = acc[-1]
                    if ns < r.space:
                        raise Exception()
                    elif ns == r.space:
                        na.append(r)
                        break
                    elif ns > r.space:
                        s2, a2 = acc.pop()
                        if acc[-1][1][-1].comma != True:
                            raise Exception('wrong comma 5')
                        acc[-1][1].append(Block(s2, a2))
                    else:
                        raise Exception()
            else:
                raise Exception()
                 




def read_line(se):
    start = False
    space = ''
    acc = []
    while True:
        ch, se = se.pop()
        #print('#',repr(ch))
        if start == False:
            if ch == ' ':
                space += ' '
                continue
            elif ch == '\n':
                return None, se
            elif ch == '\0':
                return None, se.push()
            else:
                start = True
                se.push()
        
        if ch == " ":
            pass
        elif ch == "\0":
            return Line.new(space, acc), se.push()
        elif ch == "\n":
            return Line.new(space, acc), se
        else:
            r, se =  read_one(se.push())
            #print(repr(r))
            acc.append(r)
        
def read_one(se):
    ch, se = se.pop()
    if ch in sign:
        return read_sign(se.push())
    elif ch in '"\'':
        return read_str(se.push())
    elif ch in num:
        return read_num(se.push())
    elif ch in ab_:
        return read_word(se.push())
    elif ch == '(':
        return read_tuplelike(se)
    elif ch == '[':
        return read_list(se)
    else:
        raise Exception(repr(ch))


def read_word(se):
    acc = ""
    while True:
        ch, se = se.pop()
        if ch in abnum_:
            acc += ch
        else:
            return Word(acc), se.push()

def read_sign(se):
    acc, se = se.pop()
    while True:
        ch, se = se.pop()
        if ch in find_multi(acc):
            acc += ch
        else:
            return Word(acc), se.push()

def read_str(se):
    ty, se = se.pop()
    acc = ""
    while True:
        ch, se = se.pop()
        if ch != ty:
            acc += ch
        else:
            return String(acc), se

def read_num(se):
    acc = ""
    acc2 = None
    while True:
        ch, se = se.pop()
        if ch in num:
            if acc2 is None:
              acc += ch
            else:
              acc2 += ch
        elif ch == '.':
            acc2 = ''
        else:
            if acc2 is None:
                return Num(int(acc)), se.push()
            else:
                return Num(float(acc+'.'+acc2)), se.push()

def read_tuplelike(se):
    acc = []
    subacc = []
    comma = False
    while True:
        ch, se = se.pop()
        if ch == ' ':
            pass
        elif ch == ',':
            acc.append(subacc)
            subacc = []
            comma = True
        elif ch == ')':
            if len(subacc) > 0:
                acc.append(subacc)
            return RawTuple(acc, comma), se
        else:
            comma = False
            r, se = read_one(se.push())
            subacc.append(r)


def read_list(se):
    acc = []
    subacc = []
    while True:
        ch, se = se.pop()
        if ch == ' ':
            pass
        elif ch == ',':
            acc.append(subacc)
            subacc = []
        elif ch == ']':
            if len(subacc) > 0:
                acc.append(subacc)
            return RawList(acc), se
        else:
            #print(99, repr(se.peek(5)))
            r, se = read_one(se.push())
            #print(77, repr(se.peek(5)))
            subacc.append(r)


from dataclasses import dataclass

@dataclass
class Word:
    s: str

    def __eq__(self, other):
        return isinstance(other, Word) and other.s == self.s

    def __repr__(self):
        return f"{self.s}"



@dataclass
class Num:
    n: object

    def __repr__(self):
        return f"{self.n}"

@dataclass
class String:
    s: str

    def __repr__(self):
        return f"'{self.s}'"

@dataclass
class RawTuple:
    l: list
    hascomma: bool
    
    def __repr__(self):
        s = repr(self.l)[1:-1]
        if self.hascomma:
            return f"(,{s})"
        else:
            return f"({s})"

@dataclass
class RawList:
    l: list

    def __repr__(self):
        return repr(self.l)

@dataclass
class Line:
    space: str
    l: list
    comma: bool
    
    @classmethod
    def new(cls, space, l):
        if len(l) > 0 and l[-1] == Word(':'):
            return cls(space, l[:-1], True)
        else:
            return cls(space, l, False)
  

    
    def __repr__(self):
        s = repr(self.l)[1:-1]
        if self.comma:
            ex = ':'
        else:
            ex = ''
        return f"<{ex}Line{repr(self.space)} {s}>"


@dataclass
class Block:
    space: str
    l: list

    def __repr__(self):
        return "<Block>"

@dataclass
class Doc:
    l: list
    
    def __repr__(self):
        return "<Doc>"


def scan(s):
    se = Stream(s.replace('\t', ' ') + '\0')
    r, se = read_doc(se)
    return r

def show(o):
  from tool_treeprint import tree
  
  def name(x):
    return repr(x)

  def member(x):
    if type(x) is Doc:
        return x.l
    elif type(x) is Block:
        return x.l
    else:
        return []
  
  tree(o, name, member)

def test(s):
  r = scan(s)
  show(r)
###########
if __name__ == '__main__':

  s = '''
    
x
for (i, j) in range(5).reverse()
  312 + 0.56 
  print(hello, 'world', \"im\" )
  
  
  if [] [1, 2 ed, 3 3 3] [6,,]
       2+= bb + a
     elif 
       [1, [2, [f]]] 2
       
    f(3)
  g.l[2][f(4)](,)
     
     while 1
       10 + 100
'''

  ss = '''
    
f(x)
g.ll
  
45
  22
    33
  23
    
    
'''
  s = """
a = input()
if a < 1:
    x.l[0] = 1
    l[0].x = 1
    3
elif a < 2:
    (x, y) = (y, x)
    4
print(5)

for i in range(3):
  for j in range(3):
    print(i * j) / 2
    print()
  print


dict()
attr1:
    2
attr2:
    3

    """
  
   
  test(s)
  

